package cs236369.webserver;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpServerConnection;
import org.apache.http.HttpVersion;
import org.apache.http.StatusLine;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpDateGenerator;

public class RequestHandler implements Runnable {

	private Request request;

	public RequestHandler(Request _request) {
		request = _request;
	}

	@Override
	public void run() {
		// check if file/directory exist
		File file = null;
		file = new File(request.getPath());
		if ((file == null) || (!file.exists()) || (!file.canRead())) {
			generateErrorPage(404);
		}else{
			// split GET POST handling
			if (request.getHttpMethod().equals("GET")) {
				handleGet(file);
			} else {
				handlePost(file);
			}
		}
		
		try {
			request.getSocket().close();
		} catch (IOException e) {
			// TODO handle
			e.printStackTrace();
		}
	}

	private void generateErrorPage(int errorCode) {
		StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,
				errorCode, (errorCode == 404) ? "File Not Found"
						: "Bad Request");
		String errorPage = "<html><head><title>Error " + errorCode
				+ "</title></head>";
		errorPage += "<body><h1>Error " + errorCode + "</h1>";
		errorPage += "</br></hr><br/> A team of well trained advarcks has been despached to deal with the problem";
		errorPage += "</body></html>";
		generateHttpResponseHtml(statusLine, errorPage,true);
	}
	
	private void sendResponseToClient(HttpResponse httpResponse){
		Socket socket = request.getSocket();
		HttpParams params = new BasicHttpParams();
		DefaultHttpServerConnection serverConn = new DefaultHttpServerConnection();
		try {
			serverConn.bind(socket, params);
			serverConn.sendResponseHeader(httpResponse);
			serverConn.sendResponseEntity(httpResponse);
		} catch (HttpException e) {
			//TODO: Handle
			e.printStackTrace();
		} catch (IOException e) {
			//TODO: Handle
			e.printStackTrace();
		}
	}
	private void generateFileListPage(File file) {
		String[] files = file.list();
		String host = request.getHttpParams().get("host");
		int dotPos = host.indexOf(":");
		if (dotPos > -1) host = host.substring(0, dotPos);
		String fileListPage = "<html><head><title>"+ file.getPath() +" files</title></head>";
		fileListPage += "<body><h1>" + file.getPath() + "</h1></br></hr></br></br><ul>";
		for(int i = 0; i < files.length; i++){
			fileListPage += "<li>";
			fileListPage += "<a href = \"" + host + files[i] + " \" alt = \"Directory File\">";
			fileListPage += host + files[i] + "</a>";
			fileListPage += "</li>";
		}
		fileListPage += "</ul></body></html>";
		StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
		generateHttpResponseHtml(statusLine, fileListPage, false);
	}
	
	private void generateHttpResponseHtml(StatusLine statusLine,String html, boolean isError){
		HttpResponse httpResponse = new BasicHttpResponse(statusLine);
		HttpEntity httpEntity = new ByteArrayEntity(html.getBytes());
		if (isError){
			httpResponse.addHeader("Date", new HttpDateGenerator().getCurrentDate());
			httpResponse.addHeader("Connection","close");
		}
		httpResponse.setEntity(httpEntity);
		sendResponseToClient(httpResponse);
	}

	private void handlePost(File file) {
		// check if path is to a specificly handeled type
		// if so, handle request
		String fileName = file.getName();
		int dotPos = fileName.lastIndexOf('.');
		String fileExtension = fileName.substring((dotPos == -1)? 0: dotPos);
		for (TypeHandler t :TypeHandler.getTypes()){
			if(fileExtension.equals(t.toString())){
				handleSpecificType(t,file);
				return;
			}
		}
		// else send error page 400
		generateErrorPage(400);
	}

	private void handleGet(File file) {
		// check if path is a directory or a file
		// if directory send page describing dir contents + links
		if (file.isDirectory()){
			generateFileListPage(file);
			return;
		}
		// if file check specific types and handle seperatly
		String fileName = file.getName();
		int dotPos = fileName.lastIndexOf('.');
		String fileExtension = fileName.substring((dotPos == -1)? 0: dotPos);
		for (TypeHandler t :TypeHandler.getTypes()){
			if(fileExtension.equals(t.toString())){
				handleSpecificType(t,file);
				return;
			}
		}
		// if not specific send the html/html file as is with a 200 code
			//reading the file into a string and sending it!
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
		} catch (FileNotFoundException e) {
			// TODO remove! can't be here!
			e.printStackTrace();
		}
		String html = "";
		String line = null;
		try {
			while((line = reader.readLine()) != null)
			{
				html += line;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
		generateHttpResponseHtml(statusLine, html, false);
	}

	private void handleSpecificType(TypeHandler typeHandler, File file) {

	}
	

}
